ε OPTIMIZACION EN ASSEMBLER (III) ε ------------------------------- Todos los que tienen un grado avanzado de conocimientos de ensamblador y procesos internos del procesador, saben que hay ciertas instrucciones que por su cálculo interno y todo eso, son bastante lentas. Entre ellas están las instrucciones δMULπ, δDIVπ, etc. Vamos a verlas una por una: φ MULπ La instrucción δMULπ es fácilmente emulable, y llamarla directamente es bastante lento. En ciertos casos, nos convendrá sustituirla por un grupo de instrucciones que irán más rápidas en su conjunto que a la hora de hacer δMULπ. Estos casos son, por ejemplo, a la hora de multiplicar por una potencia de 2. La manera: Γ MOV AX, 1234h Γ MOV CX, 0002 Γ MUL AX gasta mucho procesador y va despacio, gastando bastantes tics de reloj del pro- cesador. Otra manera de hacer esto mismo mucho más rápido es: Γ MOV AX, 1234h Γ SHL AX, 1 Recordemos que las operaciones a nivel de bits son siempre muy rápidas, y para multiplicar por las potencias de dos (siempre que no rebasemos el re- gistro) podemos utilizar desplazamiento de bits a la izquierda. Un ejemplo muy bueno de esta práctica es la rutina (ya casi un standard de la programación gráfica) ΩPonPixelπ. En una resolución 320x200x256 (VGA modo 13h, el de la mayoría de los juegos de ordenador), para poner un pixel del color CL en la posición en pantalla BX,DX habrá que aplicar la siguiente fór- mula: Γ PosicionMemo = PosY * 320 + PosX Γ A000:[PosicionMemo] = Color Esto, aplicado a ensamblador, nos daría que hay que multiplicar DX por 320 y sumarle BX, y después mover en la posición de memoria que nos ha dado la formulita el registro CL. Pero lo que no vamos a hacer es multiplicar por 320 porque a la hora de repetir muchas veces la llamada a la rutina, esto se tra- duce en una pérdida de velocidad alarmante. Entonces echamos mano de la ventaja de los desplazamientos de bits: φES=A000h, CL=Color, BX=PosX, DX=PosY Σ No optimizado Optimizado Σ ------------- ---------- Γ MOV AX, 0320d ROR DX, 8 Γ MUL DX ADD BX, DX Γ ADD BX, DX ROR DX, 2 Γ MOV ES:[BX], CL ADD BX, DX Γ MOV ES:[BX], CL En la primera rutina aplicamos la instrucción δMULπ, que es la lenta. En la optimizada, nos encontramos con dos desplazamientos de bits y dos sumas, que en realidad es muchísimo más rápido que la instrucción δMULπ. Repasemos la segun- da rutina paso a paso: ∩1) Multiplica DX por 256 π(desplazamiento de 8 bits a la izquierda) ∩2) Suma a BX el valor obtenido ∩3) Multiplica DX por 64π (desplaza 2 bits a la derecha, pero como si hubiera desplazado 6 bits a la izquierda el DX inicial). ∩4) Suma a BX el valor obtenido ∩5) Pone el color en la memoria de vídeo Para hacer esto, hemos echado mano de las matemáticas y de la propie- dad distributiva: δY*320+X = Y*(256+64)+X = Y*256+Y*64+X Entonces, para optimizar una multiplicación tenemos que repartir la constante que multiplica en potencias de dos, y utilizar desplazamientos de bits. Pero siempre sin pasarse, claro. Si hay que hacer 5 o 6 desplazamientos con sus respectivas sumas, conviene utilizar δMULπ. Por cierto, no hay que olvidar que estas maneras son flexibles, y no hay por qué usar siempre sumas. Si tuviéramos que multiplicar un número por 63 sería lo mismo que multiplicarlo por 64 y restarle el número inicial. Hay que encontrar una manera de hacerlo más rápido, y la suma es tan rápida como la resta. φ DIV Para dividir, es bastante más restringido el tema, porque sólo se pue- den aplicar los desplazamientos de bits cuando se divide entre potencias de dos, y siempre teniendo en cuenta de que si se utilizan no tendremos acceso al resto. Pero en casos como hacer medias, y todo eso, los desplazamientos están "bien vistos". φ LOOP Al menos hasta el Pentium, la instrucción δLOOPπ es más lenta que usar el par δDEC CX/JNZ ...π , y como normalmente no programamos sólo para Pentium, es recomendable usar esto último. Además, tiene la ventaja de que podemos usar cualquier registro como contador, no sólo CX. Entonces, un algoritmo de repeti- ción será más rápido de esta manera: Σ Manera "lenta" Manera "rápida" Σ -------------- --------------- Γ ... π; Algoritmo Γ ... π; Algoritmo Γ LOOP InicioAlgoritmo DEC CX Γ JNZ InicioAlgoritmo Con esto arañaremos un ciclo de reloj al algoritmo en procesadores in- feriores al Pentium, que nos servirá de mucho en procesos en los que tengamos que llamar a la rutina muchas veces. Y éstas son las más importantes. Sólo hay que recordar que las opera- ciones a nivel de bits son las más rápidas, y siempre que podamos traducir un proceso sólo (o en su mayoría) a operaciones con bits habremos ganado en velo- cidad. Hasta el próximo número. ∞Líyak el Oscuroπ